#ifndef _LOCK_FREE_SLIST_H
#define _LOCK_FREE_SLIST_H


class _atomic_freelist
{
public:
	struct node 
	{
		node* _M_next;
	};

	_atomic_freelist() 
	{
		_M._M_data._M_top       = 0;
		_M._M_data._M_sequence  = 0;
	}

	void push(node* __item) 
	{
		__asm
		{
			mov             esi, this;
			mov             ebx, __item;
			mov             eax, [esi];              // _M._M_data._M_top
			mov             edx, [esi+4];            // _M._M_data._M_sequence
L1:
			mov             [ebx], eax;              // __item._M_next = _M._M_data._M_top
			lea             ecx, [edx+1];            // new sequence = _M._M_data._M_sequence + 1
			lock cmpxchg8b  qword ptr [esi];
			jne             L1;                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
		}
	}
	node* pop() 
	{
		__asm
		{
			mov             esi, this;
			mov             eax, [esi];              // _M._M_data._M_top
			mov             edx, [esi+4];            // _M._M_data._M_sequence
L1: 
			test            eax, eax;                // _M_top == NULL?
			je              L2;                      // Yes, we're done
			mov             ebx, [eax];              // new top = _M._M_data._M_top->_M_next
			lea             ecx, [edx+1];            // new sequence = _M._M_data._M_sequence + 1
			lock cmpxchg8b  qword ptr [esi];
			jne             L1;                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
L2:
		}
	}

	node* clear()
	{
		__asm
		{
			mov             esi, this;
			mov             eax, [esi];              // _M._M_data._M_top
			mov             edx, [esi+4];            // _M._M_data._M_sequence
L1: 
			test            eax, eax;                // _M_top == NULL?
			je              L2;                      // Yes, we're done
			xor             ebx,ebx;                 // We're attempting to set _M._M_data._M_top to NULL
			lea             ecx, [edx+1];            // new sequence = _M._M_data._M_sequence + 1
			lock cmpxchg8b  qword ptr [esi];
			jne             L1;                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
L2:
		}
	}

private:
	union 
	{
		__int64     _M_align;
		struct {
			node*           _M_top;         // Topmost element in the freelist
			unsigned int    _M_sequence;    // Sequence counter to prevent "ABA problem"
		} _M_data;
	} _M;

};


#endif /* _LOCK_FREE_SLIST_H */
